package com.uprr.netcontrol.starmap.neo4j.dao;

import static org.neo4j.helpers.collection.MapUtil.map;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Expander;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.kernel.Traversal;
import org.springframework.data.neo4j.conversion.ResultConverter;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.rest.RestEntity;
import org.springframework.data.neo4j.support.query.QueryEngine;
import org.springframework.data.neo4j.template.Neo4jTemplate;
import org.springframework.transaction.PlatformTransactionManager;

import com.uprr.netcontrol.starmap.dto.BusinessFunctionDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionEventTypeDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionOtherDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionServiceTypeDTO;
import com.uprr.netcontrol.starmap.dto.ContainerClusterDTO;
import com.uprr.netcontrol.starmap.dto.ContainerClusterServerDTO;
import com.uprr.netcontrol.starmap.dto.DeploymentUnitDTO;
import com.uprr.netcontrol.starmap.dto.DistributionPackageDTO;
import com.uprr.netcontrol.starmap.dto.HostDTO;
import com.uprr.netcontrol.starmap.dto.MessageChannelInstanceDTO;
import com.uprr.netcontrol.starmap.dto.MessagingChannelDTO;
import com.uprr.netcontrol.starmap.dto.RepositoryDTO;
import com.uprr.netcontrol.starmap.dto.ResourceDTO;
import com.uprr.netcontrol.starmap.dto.ResourceEventTypeDTO;
import com.uprr.netcontrol.starmap.dto.ResourceServiceTypeDTO;
import com.uprr.netcontrol.starmap.dto.ServerClusterDTO;
import com.uprr.netcontrol.starmap.dto.ServerClusterServerDTO;
import com.uprr.netcontrol.starmap.persistence.DeploymentUnitDao;

public class DefaultGraphDataDao extends Neo4jTemplate implements
		DeploymentUnitDao {

	private static final String NODE_INDEX = "nodeindex";

	// private static final String RELATIONSHIP_INDEX = "relationsindex";

	private Node defaultNode = null;

	private Node rootNode = null;

	// private static final String NEO4J_REST_ADAPTER_PATH = "http://173.229.213.40:7474/neodb/rest/starmap/graph";
	private static final String NEO4J_REST_ADAPTER_PATH = "http://vx1391.uprr.com:7474/neodb/rest/starmap/graph";

	private static final String NAME = "name";

	private static final String TYPE = "type";

	private static final String ID = "id";

	private static final String ENVIRONMENT = "environment";

	private static final String NET_CONTROL = "NetControl";

	private static final Map<String, Object> EMPTY_RELATIONSHIP_MAP = new HashMap<String, Object>();

	private static final String OPERATING_SYSTEM = "operatingSystem";

	private static final String DOMAIN = "domain";

	private static final String CLUSTER_NODE = "clusterNode";

	private static final String DEPLOYMENT_STRATEGY = "deploymentStrategy";

	private static final String DIRECTION = "direction";

	private static final String CONNECTION_FACTORY = null;

	private static final String VERSION = "version";

	private static final String ARTIFACT_ID = "artifactId";

	private static final String BUSINESS_DESCRIPTION = "businessDescription";

	// for Relationship Indexes
	// private Relationship defaultRelation = null;

	public DefaultGraphDataDao(final GraphDatabase graphDatabase) {
		this(graphDatabase, null);
		
		this.rootNode = getRootNode();
	}

	public DefaultGraphDataDao(final GraphDatabase graphDatabase,
			final PlatformTransactionManager transactionManager) {
		super(graphDatabase, transactionManager);
	}

	@Override
	public void save(final DeploymentUnitDTO rootDto) {

		if (rootNode != null && rootDto != null) {
			final Node distributionPackage = createOrUpdateDistributionPackage(	rootNode, rootDto.getDistributionPackage());
			final Node deploymentUnit = createOrUpdateDeploymentUnit(distributionPackage, rootDto);
				
			createOrUpdateEnvironment(deploymentUnit, rootDto);
			createOrUpdateDeploymentStrategy(deploymentUnit, rootDto);
		
			createOrUpdateHost(deploymentUnit, rootDto.getHost());
			
			createOrUpdateResource(deploymentUnit, rootDto.getResource());
			
			createOrUpdateBusinessFunction(deploymentUnit, rootDto.getBusinessFunction());
				
		}
	}

	private Node createOrUpdateBusinessFunctionOther(Node deploymentUnit,BusinessFunctionOtherDTO businessFunctionOther) {
		
		defaultNode = nodeIndexLookup(map(NAME,businessFunctionOther.getName(), TYPE,businessFunctionOther.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, businessFunctionOther.getName(),NAME, businessFunctionOther.getName(), TYPE,businessFunctionOther.getType(),
					ARTIFACT_ID,businessFunctionOther.getArtifactId(),BUSINESS_DESCRIPTION,businessFunctionOther.getBusinessDescription()));
			this.index(NODE_INDEX, defaultNode, NAME,businessFunctionOther.getName());
			this.index(NODE_INDEX, defaultNode, TYPE,businessFunctionOther.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.PRODUCED_AS_OTHER, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.PRODUCED_AS_OTHER,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node createOrUpdateBusinessFunctionEvent(Node deploymentUnit,BusinessFunctionEventTypeDTO event) {
		defaultNode = nodeIndexLookup(map(NAME,event.getEventName(), TYPE,event.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, event.getEventName(),NAME, event.getEventName(), TYPE,event.getType(),
					DIRECTION,event.getDirection(),VERSION,event.getVersion()));
			this.index(NODE_INDEX, defaultNode, NAME,event.getEventName());
			this.index(NODE_INDEX, defaultNode, TYPE,event.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.PUBLISHED_AS_EVENT, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.PUBLISHED_AS_EVENT,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node createOrUpdateBusinessFunctionService(Node deploymentUnit,BusinessFunctionServiceTypeDTO service) {
		defaultNode = nodeIndexLookup(map(NAME,service.getServiceName(), TYPE,service.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, service.getServiceName(),NAME, service.getServiceName(), TYPE,service.getType(),
					DIRECTION,service.getDirection(),VERSION,service.getVersion()));
			this.index(NODE_INDEX, defaultNode, NAME,service.getServiceName());
			this.index(NODE_INDEX, defaultNode, TYPE,service.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.EXPOSED_AS_SERVICE, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.EXPOSED_AS_SERVICE,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	@SuppressWarnings("unused")
	private void createOrUpdateBusinessFunction(Node deploymentUnit,List<BusinessFunctionDTO> businessFunctionsList) {
		for (BusinessFunctionDTO businessFunction : businessFunctionsList) {
			if (businessFunction.getService() != null) {
				final Node businessFunctionService=createOrUpdateBusinessFunctionService(deploymentUnit,businessFunction.getService());
			}
			if (businessFunction.getEvent() != null) {
				final Node businessFunctionEvent=createOrUpdateBusinessFunctionEvent(deploymentUnit,businessFunction.getEvent());
			}
			if (businessFunction.getBusinessFunctionOther() != null) {
				final Node businessFunctionOther=createOrUpdateBusinessFunctionOther(deploymentUnit,businessFunction.getBusinessFunctionOther());
			}
		}
	}

	
	private Node createOrUpdateResourceEvent(Node deploymentUnit,ResourceEventTypeDTO event) {
		defaultNode = nodeIndexLookup(map(NAME,event.getEventName(), TYPE,event.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, event.getEventName(),NAME, event.getEventName(), TYPE,event.getType(),
					DIRECTION,event.getDirection(),VERSION,event.getVersion()));
			this.index(NODE_INDEX, defaultNode, NAME,event.getEventName());
			this.index(NODE_INDEX, defaultNode, TYPE,event.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.SUBSCRIBES_EVENT, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.SUBSCRIBES_EVENT,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node createOrUpdateResourceService(Node deploymentUnit,ResourceServiceTypeDTO service) {
		defaultNode = nodeIndexLookup(map(NAME,service.getServiceName(), TYPE,service.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, service.getServiceName(),NAME, service.getServiceName(), TYPE,service.getType(),
					DIRECTION,service.getDirection(),VERSION,service.getVersion()));
			this.index(NODE_INDEX, defaultNode, NAME,service.getServiceName());
			this.index(NODE_INDEX, defaultNode, TYPE,service.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.CONSUMES_SERVICE, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.CONSUMES_SERVICE,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node createOrUpdateResourceRepository(Node deploymentUnit,RepositoryDTO repository) {
		defaultNode = nodeIndexLookup(map(NAME,repository.getRepositoryName(), TYPE,repository.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, repository.getRepositoryName(),NAME, repository.getRepositoryName(), TYPE,repository.getType()));
			this.index(NODE_INDEX, defaultNode, NAME,repository.getRepositoryName());
			this.index(NODE_INDEX, defaultNode, TYPE,repository.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.USES_REPOSITORY, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.USES_REPOSITORY,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node createOrUpdateresourceMessagingChannel(Node deploymentUnit,MessagingChannelDTO messagingChannel) {
		defaultNode = nodeIndexLookup(map(NAME,messagingChannel.getName(), TYPE,messagingChannel.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, messagingChannel.getName(),NAME, messagingChannel.getName(), TYPE,messagingChannel.getType(),
					DIRECTION,messagingChannel.getDirection(),CONNECTION_FACTORY,messagingChannel.getConnectionFactories()));
			this.index(NODE_INDEX, defaultNode, NAME,messagingChannel.getName());
			this.index(NODE_INDEX, defaultNode, TYPE,messagingChannel.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.USES_MESSAGE_CHANNEL, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.USES_MESSAGE_CHANNEL,EMPTY_RELATIONSHIP_MAP);
		}
		
		if(messagingChannel.getInstance()!=null){
			createOrUpdateresourceMessagingChannelInstance(defaultNode,messagingChannel.getInstance());
		}
		return defaultNode;
	}
	
	private void createOrUpdateresourceMessagingChannelInstance(Node resourceMessagingChannel, MessageChannelInstanceDTO instance) {
		defaultNode = nodeIndexLookup(map(NAME,instance.getInstanceName(), TYPE,instance.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, instance.getInstanceName(),NAME, instance.getInstanceName(), TYPE,instance.getType()));
			this.index(NODE_INDEX, defaultNode, NAME,instance.getInstanceName());
			this.index(NODE_INDEX, defaultNode, TYPE,instance.getType());

			createRelationship(resourceMessagingChannel,defaultNode, RelTypes.MESSAGE_CHANNEL_INSTANCE, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(resourceMessagingChannel,defaultNode, RelTypes.MESSAGE_CHANNEL_INSTANCE,EMPTY_RELATIONSHIP_MAP);
		}
	}

	@SuppressWarnings("unused")
	private void createOrUpdateResource(Node deploymentUnit,List<ResourceDTO> resourcesList) {
		for (ResourceDTO resource : resourcesList) {
			if (resource.getMessagingChannel()!= null) {
				final Node resourceMessagingChannel=createOrUpdateresourceMessagingChannel(deploymentUnit,resource.getMessagingChannel());
			} 
			if (resource.getRepository() != null) {
				final Node resourceRepository=createOrUpdateResourceRepository(deploymentUnit,resource.getRepository() );
			}
			if (resource.getService() != null) {
				final Node resourceService=createOrUpdateResourceService(deploymentUnit,resource.getService());
			}
			if (resource.getEvent() != null) {
				final Node resourceEvent=createOrUpdateResourceEvent(deploymentUnit,resource.getEvent() );
			}
		}
	}

	private Node createOrUpdateContainerCluster(Node deploymentUnit,ContainerClusterDTO containerCluster) {
		defaultNode = nodeIndexLookup(map(NAME,containerCluster.getIdentifier(), TYPE,containerCluster.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, containerCluster.getIdentifier(),NAME, containerCluster.getIdentifier(), TYPE,containerCluster.getType(),
					DOMAIN,containerCluster.getDomain()));
			this.index(NODE_INDEX, defaultNode, NAME,containerCluster.getIdentifier());
			this.index(NODE_INDEX, defaultNode, TYPE,containerCluster.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.IS_HOSTED_ON, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.IS_HOSTED_ON,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}
	
	private void createOrUpdateContainerClusterHost(Node containerCluster,ContainerClusterDTO containerClusterDTO) {
		for(ContainerClusterServerDTO containerClusterHost:containerClusterDTO.getContainerClusterServer()){
			defaultNode = nodeIndexLookup(map(NAME, containerClusterHost.getName(),TYPE, CLUSTER_NODE));
			if (defaultNode == null) {
				defaultNode = createNode(map(ID, containerClusterHost.getName(), NAME, containerClusterHost.getName(),TYPE, CLUSTER_NODE));
				this.index(NODE_INDEX, defaultNode, NAME,containerClusterHost.getName());
				this.index(NODE_INDEX, defaultNode, TYPE,CLUSTER_NODE);
				
				createRelationship(containerCluster,defaultNode, RelTypes.CONTAINS, EMPTY_RELATIONSHIP_MAP);
			}else{
				findOrCreateRelationship(containerCluster,defaultNode, RelTypes.CONTAINS,EMPTY_RELATIONSHIP_MAP);
			}
			
		}
	}


	private Node createOrUpdateServerCluster(Node deploymentUnit,ServerClusterDTO serverCluster) {
		defaultNode = nodeIndexLookup(map(NAME, serverCluster.getIdentifier(),TYPE, serverCluster.getType()));
		findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.IS_HOSTED_ON,EMPTY_RELATIONSHIP_MAP);
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, serverCluster.getIdentifier(),	NAME, serverCluster.getIdentifier(), TYPE,serverCluster.getType(),
					OPERATING_SYSTEM,serverCluster.getOperatingSystem()));
			this.index(NODE_INDEX, defaultNode, NAME,serverCluster.getIdentifier());
			this.index(NODE_INDEX, defaultNode, TYPE, serverCluster.getType());

			createRelationship(deploymentUnit,defaultNode, RelTypes.IS_HOSTED_ON, EMPTY_RELATIONSHIP_MAP);
		}else{
			findOrCreateRelationship(deploymentUnit,defaultNode, RelTypes.IS_HOSTED_ON,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}
	
	private void createOrUpdateServerClusterHost(Node serverCluster,ServerClusterDTO serverClusterDTO) {
		for(ServerClusterServerDTO serverClusterHost:serverClusterDTO.getServerClusterServer()){
			defaultNode = nodeIndexLookup(map(NAME, serverClusterHost.getName(),TYPE, CLUSTER_NODE));
			if (defaultNode == null) {
				defaultNode = createNode(map(ID, serverClusterHost.getName(), NAME, serverClusterHost.getName(),TYPE, CLUSTER_NODE));
				this.index(NODE_INDEX, defaultNode, NAME,serverClusterHost.getName());
				this.index(NODE_INDEX, defaultNode, TYPE,CLUSTER_NODE);
				
				createRelationship(serverCluster,defaultNode, RelTypes.CONTAINS, EMPTY_RELATIONSHIP_MAP);
			}else{
				findOrCreateRelationship(serverCluster,defaultNode, RelTypes.CONTAINS,EMPTY_RELATIONSHIP_MAP);
			}
			
		}
	}

	
	private void createOrUpdateHost(Node deploymentUnit, List<HostDTO> hostsList) {
		for (HostDTO host : hostsList) {
			if (host.getServerCluster() != null) {
				final Node serverCluster=createOrUpdateServerCluster(deploymentUnit,host.getServerCluster());
				createOrUpdateServerClusterHost(serverCluster,host.getServerCluster());
			} else {
				final Node containerCluster=createOrUpdateContainerCluster(deploymentUnit,host.getContainerCluster());
				createOrUpdateContainerClusterHost(containerCluster,host.getContainerCluster());
			}
		}
	}

	private void createOrUpdateDeploymentStrategy(final Node deploymentUnit,final DeploymentUnitDTO root) {
		deploymentUnit.setProperty(DEPLOYMENT_STRATEGY, root.getDeploymentStrategy());
	}

	
	private void createOrUpdateEnvironment(final Node deploymentUnit,final DeploymentUnitDTO root) {
		deploymentUnit.setProperty(ENVIRONMENT, root.getEnvironmentType());
	}

	private Node createOrUpdateDeploymentUnit(final Node deploymentPackage,	final DeploymentUnitDTO root) {
		defaultNode = nodeIndexLookup(map(NAME, root.getName(), TYPE,root.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, root.getName(), NAME,root.getName(), TYPE, root.getType()));
			this.index(NODE_INDEX, defaultNode, NAME, root.getName());
			this.index(NODE_INDEX, defaultNode, TYPE, root.getType());

		}
		findDeploymentPackageDeploymentUnitRelations(deploymentPackage,defaultNode, RelTypes.HAS_DEPLOYMENT_UNITS);
		return defaultNode;

	}

	private Node createOrUpdateDistributionPackage(final Node rootNode,	final DistributionPackageDTO distributionPackageDTO) {
		final String nodeName = distributionPackageDTO.getName();
		defaultNode = nodeIndexLookup(map(NAME, nodeName, TYPE,	distributionPackageDTO.getType()));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, nodeName, NAME, nodeName, TYPE,distributionPackageDTO.getType()));
			this.index(NODE_INDEX, defaultNode, NAME, nodeName);
			this.index(NODE_INDEX, defaultNode, TYPE,distributionPackageDTO.getType());

			createRelationship(rootNode, defaultNode,RelTypes.MANAGES_DISTRIBUTION_PACKAGES,EMPTY_RELATIONSHIP_MAP);
		}
		return defaultNode;
	}

	private Node getRootNode() {
		defaultNode = nodeIndexLookup(map(NAME, NET_CONTROL, TYPE, NET_CONTROL));
		if (defaultNode == null) {
			defaultNode = createNode(map(ID, NET_CONTROL, NAME, NET_CONTROL,TYPE, NET_CONTROL));
			this.index(NODE_INDEX, defaultNode, NAME, NET_CONTROL);
			this.index(NODE_INDEX, defaultNode, TYPE, NET_CONTROL);
		}
		return defaultNode;
	}

	private Node nodeIndexLookup(Map<String, Object> map) {
		Node n = null;
		try {
			StringBuilder query = new StringBuilder();
			int i = 1;
			for (Entry<String, Object> entry : map.entrySet()) {
				query.append(entry.getKey() + ":");
				query.append(entry.getValue());

				if (i < map.size())
					query.append(" AND ");
				i++;
			}
			n = this.lookup(NODE_INDEX, query.toString()).to(Node.class).single();
		} catch (Exception e) {
			return null;
		}
		return n;
	}
	
	private Node findOrCreateNodeAndRelations(String name,String type,Map<String, Object> indexLookupMap,Map<String, Object> nodePropsMap){
		
		return null;
		
	}
	
	private void findOrCreateRelationship(Node node1, Node node2,RelTypes relationshipType,Map<String, Object> relationshipMap) {
		TraversalDescription traversalDescription = Traversal.description().relationships(relationshipType).evaluator(Evaluators.atDepth(1));

		for (Node node : traversalDescription.traverse(node1).nodes()) {
			if(node==node2) 	return;
		}
		createRelationship(node1,node2,relationshipType, relationshipMap);

	}

	private void findDeploymentPackageDeploymentUnitRelations(final Node parent, final Node child, final RelationshipType relType) {
		Relationship relation = child.getSingleRelationship(relType,Direction.INCOMING);
		if (relation != null) {
			if (relation.getOtherNode(child) == parent)
				return;
			else
				relation.delete();
		}
		relation = createRelationship(parent, child, relType,EMPTY_RELATIONSHIP_MAP);
	}

	
	

	// private void getFeatureGroups(final Node deploymentUnit, final
	// List<FeatureGroupDTO> featureGroupDtoList) {
	//
	// }
	//
	// private void getBusinessFunctions(final Node deploymentUnit, final
	// List<BusinessFunctionDTO> list) {
	//
	// }

	private static enum RelTypes implements RelationshipType {
		MESSAGE_CHANNEL_INSTANCE ,SUBSCRIBES_EVENT,USES_REPOSITORY, CONSUMES_SERVICE, IS_HOSTED_ON, USES_MESSAGE_CHANNEL,CONTAINS, 
		MONITORS, ENVIRONMENT, MANAGES_DISTRIBUTION_PACKAGES, HAS_DEPLOYMENT_UNITS,EXPOSED_AS_SERVICE,PUBLISHED_AS_EVENT,PRODUCED_AS_OTHER;
	}

	/*public class NodeResultConverter implements	ResultConverter<PropertyContainer, Node> {

		@Override
		public Node convert(final PropertyContainer value,final Class<Node> type) {
			return null;
		}

	}
*/
	// @Override
	public File retreive() {

		File compressedGraphXml = null;
		try {
			generateGraphXml();
			getGraphXml();
			compressedGraphXml = compressXML();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return compressedGraphXml;
	}

	/**
	 * query neo4j graph database and save as xml in the neo4j server
	 */
	public void generateGraphXml() throws URISyntaxException {
		final String gremlinQuery = "g.saveGraphML('data/graph.xml')";
		this.execute(gremlinQuery, null);
	}

	/**
	 * get graph xml through Neo4j Rest plugin and save as XML
	 */
	public void getGraphXml() throws IOException {
		FileOutputStream fos = null;
		try {
			// invoke Neo4j rest plugin
			final URL neo4jRestService = new URL(NEO4J_REST_ADAPTER_PATH);
			final ReadableByteChannel rbc = Channels.newChannel(neo4jRestService.openStream());

			// save as xml into local server
			fos = new FileOutputStream("netControl.xml");
			fos.getChannel().transferFrom(rbc, 0, 1 << 24);
		} finally {
			IOUtils.closeQuietly(fos);
		}
	}

	/**
	 * compress and return graph xml
	 */
	public File compressXML() throws IOException {

		File compressedFile = null;
		ZipOutputStream out = null;
		FileInputStream in = null;
		BufferedInputStream buff = null;
		try {
			// These are the files to include in the ZIP file
			final String sourceFilePath = "netControl.xml";

			// Create a buffer for reading the files
			final byte[] buf = new byte[2048];

			// Create the ZIP file
			final String target = "netControl.zip";
			out = new ZipOutputStream(new FileOutputStream(target));

			// Compress the files

			in = new FileInputStream(sourceFilePath);

			buff = new BufferedInputStream(in);

			// Add ZIP entry to output stream.
			out.putNextEntry(new ZipEntry("netControl.xml"));

			// Transfer bytes from the file to the ZIP file
			int len;
			while ((len = buff.read(buf)) > 0) {
				out.write(buf, 0, len);
			}

			compressedFile = new File(target);

			return compressedFile;
		} finally {
			// Complete the entry
			out.closeEntry();
			IOUtils.closeQuietly(in);
			// Complete the ZIP file
			IOUtils.closeQuietly(out);
		}
	}

}
